package com.muyu.payment.service.impl;

import com.muyu.payment.domain.PaymentIndent;
import com.muyu.payment.domain.PaymentOrder;
import com.muyu.payment.domain.model.PaymentOrderSaveModel;
import com.muyu.payment.service.PaymentDataSyncService;
import com.muyu.payment.service.PaymentIndentService;
import com.muyu.payment.service.PaymentOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 支付数据同步服务实现
 *
 * @author muyu
 * @date 2025-09-18
 */
@Slf4j
@Service
public class PaymentDataSyncServiceImpl implements PaymentDataSyncService {

    @Autowired
    private PaymentIndentService paymentIndentService;

    @Autowired
    private PaymentOrderService paymentOrderService;

    /**
     * 同步支付订单到支付记录表
     * @param paymentIndent 支付订单
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncIndentToOrder(PaymentIndent paymentIndent) {
        try {
            // 检查支付记录表是否已存在该订单
            PaymentOrder existingOrder = paymentOrderService.getByOrderNo(paymentIndent.getOrderNo());
            if (existingOrder != null) {
                log.info("支付记录已存在，订单号：{}", paymentIndent.getOrderNo());
                return true;
            }

            // 状态映射：PaymentIndent -> PaymentOrder
            // PaymentIndent: 1-待支付, 2-已支付, 3-已完成, 4-已取消
            // PaymentOrder: 1-待支付, 2-已支付, 3-已完成, 4-已取消, 8-已关闭, 9-已退款
            Long orderStatus = switch (paymentIndent.getOrderStatus()) {
                case 1 -> 1L; // 待支付
                case 2 -> 2L; // 已支付
                case 3 -> 3L; // 已完成
                case 4 -> 4L; // 已取消
                default -> 1L;
            };

            // 创建支付记录
            // 保持数据一致性，使用PaymentIndent中的原始数据
            PaymentOrderSaveModel saveModel = PaymentOrderSaveModel.builder()
                    .orderNo(paymentIndent.getOrderNo())
                    .userId(paymentIndent.getUserId())
                    .amount(paymentIndent.getAmount())
                    .orderStatus(orderStatus)
                    .subject(paymentIndent.getSubject())
                    .body(paymentIndent.getBody())
                    .expireTime(paymentIndent.getExpireTime()) // 保持数据一致性，使用原始过期时间
                    .remark(paymentIndent.getRemark())
                    .createTime(paymentIndent.getCreateTime())
                    .build();

            paymentOrderService.save(saveModel);
            log.info("同步支付订单到记录表成功，订单号：{}", paymentIndent.getOrderNo());
            return true;

        } catch (Exception e) {
            log.error("同步支付订单到记录表失败，订单号：{}", paymentIndent.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 同步支付订单到支付记录表（带支付类型）
     * @param paymentIndent 支付订单
     * @param payType 支付类型
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncIndentToOrder(PaymentIndent paymentIndent, Long payType) {
        try {
            // 检查支付记录表是否已存在该订单
            PaymentOrder existingOrder = paymentOrderService.getByOrderNo(paymentIndent.getOrderNo());
            if (existingOrder != null) {
                log.info("支付记录已存在，订单号：{}", paymentIndent.getOrderNo());
                return true;
            }

            // 状态映射：PaymentIndent -> PaymentOrder
            // PaymentIndent: 1-待支付, 2-已支付, 3-已完成, 4-已取消
            // PaymentOrder: 1-待支付, 2-已支付, 3-已完成, 4-已取消, 8-已关闭, 9-已退款
            Long orderStatus = switch (paymentIndent.getOrderStatus()) {
                case 1 -> 1L; // 待支付
                case 2 -> 2L; // 已支付
                case 3 -> 3L; // 已完成
                case 4 -> 4L; // 已取消
                default -> 1L;
            };

            // 根据支付类型设置支付渠道
            String payChannel = getPayChannelByType(payType);

            // 创建支付记录
            // 如果订单状态是已支付，设置支付时间为当前时间
            Date payTime = null;
            if (orderStatus == 2L) { // 已支付状态
                payTime = new Date();
            }
            
            PaymentOrderSaveModel saveModel = PaymentOrderSaveModel.builder()
                    .orderNo(paymentIndent.getOrderNo())
                    .userId(paymentIndent.getUserId())
                    .amount(paymentIndent.getAmount())
                    .orderStatus(orderStatus)
                    .payTime(payTime) // 设置支付时间
                    .payChannel(payChannel)
                    .payType(payType) // 从参数中获取
                    .subject(paymentIndent.getSubject())
                    .body(paymentIndent.getBody())
                    .expireTime(paymentIndent.getExpireTime()) 
                    .remark(paymentIndent.getRemark())
                    .createTime(paymentIndent.getCreateTime())
                    .build();

            paymentOrderService.save(saveModel);
            log.info("同步支付订单到记录表成功，订单号：{}，支付类型：{}", paymentIndent.getOrderNo(), payType);
            return true;

        } catch (Exception e) {
            log.error("同步支付订单到记录表失败，订单号：{}", paymentIndent.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 同步支付订单到支付记录表（带支付类型和支付时间）
     * @param paymentIndent 支付订单
     * @param payType 支付类型
     * @param payTime 支付时间
     * @param thirdTradeNo 第三方交易号
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncIndentToOrder(PaymentIndent paymentIndent, Long payType, java.util.Date payTime, String thirdTradeNo) {
        try {
            // 检查支付记录表是否已存在该订单
            PaymentOrder existingOrder = paymentOrderService.getByOrderNo(paymentIndent.getOrderNo());
            if (existingOrder != null) {
                log.info("支付记录已存在，订单号：{}", paymentIndent.getOrderNo());
                return true;
            }

            // 状态映射：PaymentIndent -> PaymentOrder
            // PaymentIndent: 1-待支付, 2-已支付, 3-已完成, 4-已取消
            // PaymentOrder: 1-待支付, 2-已支付, 3-已完成, 4-已取消, 8-已关闭, 9-已退款
            // 注意：在支付回调中，即使PaymentIndent状态是待支付，也要创建已支付的PaymentOrder记录
            Long orderStatus = switch (paymentIndent.getOrderStatus()) {
                case 1 -> 2L; // 待支付 -> 已支付（支付回调场景）
                case 2 -> 2L; // 已支付
                case 3 -> 3L; // 已完成
                case 4 -> 4L; // 已取消
                default -> 2L; // 默认已支付（支付回调场景）
            };

            // 根据支付类型设置支付渠道
            String payChannel = getPayChannelByType(payType);

            // 创建支付记录
            PaymentOrderSaveModel saveModel = PaymentOrderSaveModel.builder()
                    .orderNo(paymentIndent.getOrderNo())
                    .userId(paymentIndent.getUserId())
                    .amount(paymentIndent.getAmount())
                    .orderStatus(orderStatus)
                    .payTime(payTime) // 使用回调中的支付时间
                    .payChannel(payChannel)
                    .payType(payType) // 从参数中获取
                    .payTradeNo(thirdTradeNo) // 设置第三方交易号
                    .subject(paymentIndent.getSubject())
                    .body(paymentIndent.getBody())
                    .expireTime(paymentIndent.getExpireTime()) 
                    .remark(paymentIndent.getRemark())
                    .createTime(paymentIndent.getCreateTime())
                    .build();

            paymentOrderService.save(saveModel);
            log.info("同步支付订单到记录表成功，订单号：{}，支付类型：{}，支付时间：{}", paymentIndent.getOrderNo(), payType, payTime);
            return true;

        } catch (Exception e) {
            log.error("同步支付订单到记录表失败，订单号：{}", paymentIndent.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 检查并修复数据一致性
     * @param orderNo 订单号
     * @return 是否修复成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkAndFixDataConsistency(String orderNo) {
        try {
            PaymentIndent indent = paymentIndentService.getByOrderNo(orderNo);
            PaymentOrder order = paymentOrderService.getByOrderNo(orderNo);

            if (indent == null) {
                log.warn("支付订单不存在，订单号：{}", orderNo);
                return false;
            }

            if (order == null) {
                // 支付记录不存在，创建记录
                log.info("支付记录不存在，创建记录，订单号：{}", orderNo);
                return syncIndentToOrder(indent);
            }

            // 检查状态一致性
            boolean statusConsistent = checkStatusConsistency(indent, order);
            if (!statusConsistent) {
                log.warn("订单状态不一致，订单号：{}，支付订单状态：{}，支付记录状态：{}", 
                        orderNo, indent.getOrderStatus(), order.getOrderStatus());
                
                // 修复状态不一致
                return fixStatusInconsistency(indent, order);
            }

            return true;

        } catch (Exception e) {
            log.error("检查数据一致性失败，订单号：{}", orderNo, e);
            return false;
        }
    }

    /**
     * 批量检查并修复数据一致性
     * @return 修复的订单数量
     */
    @Override
    public int batchCheckAndFixDataConsistency() {
        int fixedCount = 0;
        try {
            // 获取所有支付订单
            List<PaymentIndent> allIndents = paymentIndentService.list();
            
            for (PaymentIndent indent : allIndents) {
                if (checkAndFixDataConsistency(indent.getOrderNo())) {
                    fixedCount++;
                }
            }
            
            log.info("批量检查数据一致性完成，修复订单数量：{}", fixedCount);
            return fixedCount;

        } catch (Exception e) {
            log.error("批量检查数据一致性失败", e);
            return fixedCount;
        }
    }

    /**
     * 检查状态一致性
     */
    private boolean checkStatusConsistency(PaymentIndent indent, PaymentOrder order) {
        // 状态映射检查
        Long expectedOrderStatus = switch (indent.getOrderStatus()) {
            case 1 -> 1L; // 待支付
            case 2 -> 2L; // 已支付
            case 3 -> 3L; // 已完成
            case 4 -> 4L; // 已取消
            default -> 1L;
        };
        
        return expectedOrderStatus.equals(order.getOrderStatus());
    }

    /**
     * 修复状态不一致
     */
    private boolean fixStatusInconsistency(PaymentIndent indent, PaymentOrder order) {
        try {
            // 以支付订单表为准，更新支付记录表状态
            Long correctStatus = switch (indent.getOrderStatus()) {
                case 1 -> 1L; // 待支付
                case 2 -> 2L; // 已支付
                case 3 -> 3L; // 已完成
                case 4 -> 4L; // 已取消
                default -> 1L;
            };

            // 更新支付记录表状态
            PaymentOrder updateOrder = PaymentOrder.builder()
                    .id(order.getId())
                    .orderNo(order.getOrderNo())
                    .userId(order.getUserId())
                    .amount(order.getAmount())
                    .orderStatus(correctStatus)
                    .payTime(order.getPayTime())
                    .payChannel(order.getPayChannel())
                    .payTradeNo(order.getPayTradeNo())
                    .subject(order.getSubject())
                    .body(order.getBody())
                    .clientIp(order.getClientIp())
                    .notifyUrl(order.getNotifyUrl())
                    .returnUrl(order.getReturnUrl())
                    .expireTime(order.getExpireTime())
                    .remark(order.getRemark())
                    .payType(order.getPayType())
                    .updateTime(new Date())
                    .build();

            paymentOrderService.updateById(updateOrder);
            log.info("修复状态不一致成功，订单号：{}，新状态：{}", order.getOrderNo(), correctStatus);
            return true;

        } catch (Exception e) {
            log.error("修复状态不一致失败，订单号：{}", order.getOrderNo(), e);
            return false;
        }
    }

    /**
     * 根据支付类型获取支付渠道
     */
    private String getPayChannelByType(Long payType) {
        if (payType == null) {
            return "unknown";
        }
        return switch (payType.intValue()) {
            case 1 -> "wxpay"; // 微信
            case 2 -> "balance"; // 余额
            case 3 -> "alipay"; // 支付宝
            default -> "unknown";
        };
    }
}